using MediatR;
using Dapper;
using System.Linq;
using RBAC.ErrorCode;
using RBAC.Domain.PurchasingManagement.PurchaseOrders;
using RBAC.Interstructrue.Base;
using RBAC.Write.Api.Application.Command.ERP.PurchasingManagement.PurchaseArrivalNotes;

namespace RBAC.Write.Api.Application.Handler.ERP.PurchasingManagement.PurchaseArrivalNotes
{
    public class AddPurchaseArrivalNoteCommandHandler : IRequestHandler<AddPurchaseArrivalNoteCommand, APIResult<int>>
    {
        private readonly IBaseRepository<ArrivalOrderInfo> _arrivalOrderRepo;
        private readonly ILogger<AddPurchaseArrivalNoteCommandHandler> _logger;
        private readonly IDbConnectionFactory _connectionFactory;

        public AddPurchaseArrivalNoteCommandHandler(
            IBaseRepository<ArrivalOrderInfo> arrivalOrderRepo,
            ILogger<AddPurchaseArrivalNoteCommandHandler> logger,
            IDbConnectionFactory connectionFactory)
        {
            _arrivalOrderRepo = arrivalOrderRepo;
            _logger = logger;
            _connectionFactory = connectionFactory;
        }

        public async Task<APIResult<int>> Handle(AddPurchaseArrivalNoteCommand request, CancellationToken cancellationToken)
        {
            try
            {
                // 基本校验
                if (string.IsNullOrWhiteSpace(request.DocCode))
                    return new APIResult<int> { Code = APIEnums.Fail, Msg = "单据编码不能为空", Data = 0 };
                if (string.IsNullOrWhiteSpace(request.SupplierId))
                    return new APIResult<int> { Code = APIEnums.Fail, Msg = "供应商ID不能为空", Data = 0 };

                // 唯一性校验（按单据编码）
                var exists = _arrivalOrderRepo.GetFirstOrDefault("DocCode = @DocCode", new { request.DocCode });
                if (exists != null)
                    return new APIResult<int> { Code = APIEnums.Fail, Msg = "单据编码已存在", Data = 0 };

                // 映射命令到实体（仅映射实体存在的字段）
                var entity = new ArrivalOrderInfo
                {
                    DocCode = request.DocCode,
                    BizType = request.BizType,
                    PurchaseOrderNo = request.PurchaseOrderNo,
                    DeliveryNote = request.DeliveryNote,
                    DocDate = request.DocDate,
                    Operator = request.Operator,
                    SupplierId = request.SupplierId,
                    DocStatus = request.DocStatus,
                    Auditor = request.Auditor,
                    Warehouse = request.Warehouse,
                    BizStatus = request.BizStatus,
                    AuditDate = request.AuditDate,
                    Progress = request.Progress,
                    Remark = request.Remark
                };

                // 持久化主表（Dapper 封装仓储）
                var newId = _arrivalOrderRepo.Create(entity);

                // 插入明细（如有）
                if (newId > 0 && request.Details != null && request.Details.Any())
                {
                    try
                    {
                        using var conn = _connectionFactory.CreateConnectionWithRetry();
                        using var tran = conn.BeginTransaction();

                        var sql = @"INSERT INTO ArrivalOrderMaterialInfo
                            (ArrivalOrderId, DocumentaryNumber, SupplierContractNo, MaterialCode, MaterialName, MainUnit,
                             Quantity, BatchNo, InboundQuantity, ArrivalDescription, IsDel)
                            VALUES
                            (@ArrivalOrderId, @DocumentaryNumber, @SupplierContractNo, @MaterialCode, @MaterialName, @MainUnit,
                             @Quantity, @BatchNo, @InboundQuantity, @ArrivalDescription, @IsDel);";

                        foreach (var d in request.Details)
                        {
                            var parameters = new
                            {
                                ArrivalOrderId = (long)newId,
                                DocumentaryNumber = d.DocumentaryNumber,
                                SupplierContractNo = d.SupplierContractNo,
                                MaterialCode = d.MaterialCode,
                                MaterialName = d.MaterialName,
                                MainUnit = d.MainUnit,
                                Quantity = d.Quantity,
                                BatchNo = d.BatchNo,
                                InboundQuantity = d.InboundQuantity,
                                ArrivalDescription = d.ArrivalDescription,
                                IsDel = false
                            };

                            var cmd = new CommandDefinition(sql, parameters, transaction: tran, commandTimeout: 60);
                            conn.Execute(cmd);
                        }

                        tran.Commit();
                    }
                    catch (Exception ex)
                    {
                        _logger?.LogError(ex, "新增采购到货单明细(ArrivalOrderMaterialInfo)失败: {Message}", ex.Message);
                        // 业务决定：明细失败不回滚主表。如需强一致，可抛出异常并在上层事务控制。
                    }
                }

                return new APIResult<int>
                {
                    Code = newId > 0 ? APIEnums.Success : APIEnums.Fail,
                    Msg = newId > 0 ? "新增采购到货单成功" : "新增采购到货单失败",
                    Data = newId
                };
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "新增采购到货单失败: {Message}", ex.Message);
                return new APIResult<int>
                {
                    Code = APIEnums.Fail,
                    Msg = "新增采购到货单异常: " + ex.Message,
                    Data = 0
                };
            }
        }
    }
}
